﻿using System;
using System.Windows.Media.Media3D;

namespace LxCFD
{
    public struct ArrowFactory
    {
        public ArrowFactory(int thetaDiv)
        {
            this.thetaDiv = thetaDiv;
            Positions = new Point3D[(thetaDiv * 3 + 3)];
            TriangleIndices = new int[(thetaDiv * 5 * 3)];
            double seg = Math.PI * 2 / thetaDiv;
            angleFactor = new (double cos, double sin)[thetaDiv];
            for (int i1 = 0; i1 < thetaDiv; i1++)
            {
                double radian = seg * i1;
                angleFactor[i1] = (Math.Cos(radian), Math.Sin(radian));
            }
        }
        private int thetaDiv;
        private (double cos, double sin)[] angleFactor;
        public Point3D[] Positions;
        public int[] TriangleIndices;
        public bool CreateArrow(Point3D basepoint, Vector3D axis, double headProportion, double tailRadius, double headRadius)
        {
            if (axis.Length == 0) return false;
            {
                Point3D[] ps = Positions;
                //添加点
                //[0](基点) [1,n]（基点周围圆圈） [n+1,2n] [2n+1] [2n+2,3n+1] [3n+2]（箭头）
                ps[0] = basepoint;
                Point3D tailPoint = ps[2 * thetaDiv + 1] = basepoint + (1 - headProportion) * axis;
                ps[3 * thetaDiv + 2] = basepoint + axis;

                (Vector3D u, Vector3D v) = VectorMath.FindVerticalVector(axis);
                int start_2n2 = 2 * thetaDiv + 2;
                int start_n1 = thetaDiv + 1;
                for (int i1 = 0; i1 < thetaDiv; i1++)
                {
                    ref var f = ref angleFactor[i1];
                    Vector3D radialV = f.cos * u + f.sin * v;
                    Vector3D tailRV = tailRadius * radialV;
                    ps[1 + i1] = (basepoint + tailRV);
                    ps[start_n1 + i1] = tailPoint + tailRV;
                    ps[start_2n2 + i1] = tailPoint + headRadius * radialV;
                }
            }
            {
                int[] ts = TriangleIndices;
                //添加三角形
                //[0,3n-1](基点周围的圆)  [3n,9n-1](圆柱部分) [9n,12n-1](tail部分) [12n,15n](箭头)
                int n = thetaDiv;
                int n21 = n * 2 + 1;
                int n32 = n * 3 + 2;
                int i = 0;
                for (; i < n - 1; i++)
                {
                    int i3 = 3 * i;
                    ts[i3] = 0;
                    ts[i3 + 1] = 2 + i;
                    ts[i3 + 2] = 1 + i;

                    int n3i6 = n * 3 + i * 6;
                    ts[n3i6] = 1 + i;
                    ts[n3i6 + 1] = 2 + i;
                    ts[n3i6 + 2] = n + 2 + i;
                    ts[n3i6 + 3] = 1 + i;
                    ts[n3i6 + 4] = n + 2 + i;
                    ts[n3i6 + 5] = n + 1 + i;

                    int n9i3 = n * 9 + i * 3;
                    ts[n9i3] = n21;
                    ts[n9i3 + 1] = 2 * n + 3 + i;
                    ts[n9i3 + 2] = 2 * n + 2 + i;

                    int n12i3 = 12 * n + 3 * i;
                    ts[n12i3] = n32;
                    ts[n12i3 + 1] = 2 * n + 2 + i;
                    ts[n12i3 + 2] = 2 * n + 3 + i;
                }
                {
                    int i3 = 3 * i;
                    ts[i3] = 0;
                    ts[i3 + 1] = 1;
                    ts[i3 + 2] = n;

                    int n3i6 = n * 3 + i * 6;
                    ts[n3i6] = n;
                    ts[n3i6 + 1] = 1;
                    ts[n3i6 + 2] = n + 1;
                    ts[n3i6 + 3] = n;
                    ts[n3i6 + 4] = n + 1;
                    ts[n3i6 + 5] = 2 * n;

                    int n9i3 = n * 9 + i * 3;
                    ts[n9i3] = n21;
                    ts[n9i3 + 1] = 2 * n + 2;
                    ts[n9i3 + 2] = 3 * n + 1;

                    int n12i3 = 12 * n + 3 * i;
                    ts[n12i3] = n32;
                    ts[n12i3 + 1] = 3 * n + 1;
                    ts[n12i3 + 2] = 2 * n + 2;
                }
            }
            return true;
        }
    }
}
